using AutoMapper;
using MediatR;
using Microsoft.EntityFrameworkCore;
using RBAC.Domain.SmartHealthcare;
using RBAC.Domain.SmartHealthcare.Hosiptial;
using RBAC.ErrorCode;
using RBAC.Interstructrue;
using RBAC.Interstructrue.Base;
using SmartHealthcare.Write.Api.Application.Command.Payment;
using System;
using System.Data;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;

namespace SmartHealthcare.Write.Api.Application.Handler.Payment
{
    /// <summary>
    /// 创建支付记录处理器
    /// </summary>
    public class CreatePaymentRecordHandler : IRequestHandler<CreatePaymentRecordCommand, APIResult<long>>
    {
        private readonly IBaseRepository<PaymentRecordModel> paymentRepository;
        private readonly IBaseRepository<InpatientRegistryModel> inpatientRegistryRepository;
        private readonly IBaseRepository<PrepaymentModel> prepaymentRepository;
        private readonly RBACDbContext db;
        private readonly IMapper mapper;
        private readonly ILogger<CreatePaymentRecordHandler> logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="paymentRepository">支付记录仓储</param>
        /// <param name="inpatientRegistryRepository">住院登记仓储</param>
        /// <param name="prepaymentRepository">预交款仓储</param>
        /// <param name="db">数据库上下文</param>
        /// <param name="mapper">对象映射器</param>
        /// <param name="logger">日志记录器</param>
        public CreatePaymentRecordHandler(
            IBaseRepository<PaymentRecordModel> paymentRepository,
            IBaseRepository<InpatientRegistryModel> inpatientRegistryRepository,
            IBaseRepository<PrepaymentModel> prepaymentRepository,
            RBACDbContext db,
            IMapper mapper,
            ILogger<CreatePaymentRecordHandler> logger)
        {
            this.paymentRepository = paymentRepository;
            this.inpatientRegistryRepository = inpatientRegistryRepository;
            this.prepaymentRepository = prepaymentRepository;
            this.db = db;
            this.mapper = mapper;
            this.logger = logger;
        }

        /// <summary>
        /// 处理创建支付记录请求
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>新创建的支付记录ID</returns>
        public Task<APIResult<long>> Handle(CreatePaymentRecordCommand request, CancellationToken cancellationToken)
        {
            APIResult<long> result = new APIResult<long>();

            try
            {
                logger.LogInformation($"开始创建支付记录，患者：{request.PatientName}，金额：{request.Amount}，支付方式：{request.PaymentMethod}");

                // 验证住院登记是否存在
                var inpatientRegistry = inpatientRegistryRepository.GetModel(request.InpatientRegistryId);
                if (inpatientRegistry == null || inpatientRegistry.IsDeleted)
                {
                    logger.LogWarning($"住院登记不存在，ID：{request.InpatientRegistryId}");
                    result.Code = APIEnums.Error;
                    result.Msg = "住院登记不存在";
                    return Task.FromResult(result);
                }

                // 获取科室名称 - 使用硬编码方式确保不会为null
                string departmentName = "未知科室";
                
                try
                {
                    // 首先检查请求中是否提供了科室名称
                    if (!string.IsNullOrEmpty(request.DepartmentName))
                    {
                        departmentName = request.DepartmentName;
                        logger.LogInformation($"使用请求提供的科室名称: {departmentName}");
                    }
                    // 如果没有提供，尝试从住院登记中获取
                    else if (inpatientRegistry != null && inpatientRegistry.DepartmentId > 0)
                    {
                        // 直接使用SQL查询获取科室名称
                        var connection = db.Database.GetDbConnection();
                        if (connection.State != System.Data.ConnectionState.Open)
                        {
                            connection.Open();
                        }
                        
                        using (var command = connection.CreateCommand())
                        {
                            command.CommandText = $"SELECT DepartmentName FROM Departments WHERE Id = {inpatientRegistry.DepartmentId} AND IsDeleted = 0";
                            var queryResult = command.ExecuteScalar();
                            
                            if (queryResult != null && queryResult != DBNull.Value)
                            {
                                departmentName = queryResult.ToString();
                                logger.LogInformation($"通过SQL查询获取科室名称: {departmentName}");
                            }
                            else
                            {
                                logger.LogWarning($"未找到ID为{inpatientRegistry.DepartmentId}的科室");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "获取科室信息失败，使用默认科室名称");
                }
                
                // 确保科室名称不为null或空
                if (string.IsNullOrEmpty(departmentName))
                {
                    departmentName = "未知科室";
                    logger.LogWarning("科室名称为空，使用默认值: 未知科室");
                }
                
                // 记录最终使用的科室名称
                logger.LogInformation($"最终使用的科室名称: {departmentName}");

                // 创建支付记录实体
                var paymentRecord = new PaymentRecordModel
                {
                    InpatientRegistryId = request.InpatientRegistryId,
                    MedicalCard = request.MedicalCard ?? string.Empty,
                    PatientName = request.PatientName ?? "未知患者",
                    DepartmentName = departmentName, // 设置科室名称，已确保不为null
                    PaymentTime = request.PaymentTime,
                    Amount = request.Amount,
                    PaymentMethod = request.PaymentMethod ?? "其他",
                    PaymentType = request.PaymentType ?? "其他",
                    TransactionNumber = request.TransactionNumber ?? string.Empty,
                    OperatorName = request.OperatorName ?? "system",
                    Remarks = request.Remarks ?? string.Empty,
                    ReceiptUrl = request.ReceiptUrl ?? string.Empty,
                    CreateTime = DateTime.Now,
                    CreateUser = request.OperatorName ?? "system"
                };
                
                // 再次确保所有字符串字段都不为null（防御性编程）
                if (string.IsNullOrEmpty(paymentRecord.DepartmentName))
                {
                    paymentRecord.DepartmentName = "未知科室";
                    logger.LogWarning("在创建实体后发现科室名称为空，已设置为默认值");
                }
                
                // 确保其他字符串字段不为null
                paymentRecord.MedicalCard ??= string.Empty;
                paymentRecord.PatientName ??= "未知患者";
                paymentRecord.PaymentMethod ??= "其他";
                paymentRecord.PaymentType ??= "其他";
                paymentRecord.TransactionNumber ??= string.Empty;
                paymentRecord.OperatorName ??= "system";
                paymentRecord.Remarks ??= string.Empty;
                paymentRecord.ReceiptUrl ??= string.Empty;
                paymentRecord.CreateUser ??= "system";

                // 记录所有字段值，用于调试
                logger.LogInformation($"准备保存支付记录，字段值如下：");
                logger.LogInformation($"InpatientRegistryId: {paymentRecord.InpatientRegistryId}");
                logger.LogInformation($"MedicalCard: '{paymentRecord.MedicalCard}'");
                logger.LogInformation($"PatientName: '{paymentRecord.PatientName}'");
                logger.LogInformation($"DepartmentName: '{paymentRecord.DepartmentName}'");
                logger.LogInformation($"PaymentMethod: '{paymentRecord.PaymentMethod}'");
                logger.LogInformation($"PaymentType: '{paymentRecord.PaymentType}'");
                logger.LogInformation($"Amount: {paymentRecord.Amount}");
                logger.LogInformation($"TransactionNumber: '{paymentRecord.TransactionNumber}'");
                logger.LogInformation($"OperatorName: '{paymentRecord.OperatorName}'");
                
                // 直接设置科室名称为固定值，确保不为null
                paymentRecord.DepartmentName = "未知科室";
                
                try
                {
                    // 使用原始SQL直接插入记录，完全绕过Entity Framework Core
                    var connection = db.Database.GetDbConnection();
                    if (connection.State != System.Data.ConnectionState.Open)
                    {
                        connection.Open();
                    }
                    
                    using (var command = connection.CreateCommand())
                    {
                        // 确保科室名称不为null
                        string safeDepartmentName = paymentRecord.DepartmentName ?? "未知科室";
                        string safePatientName = paymentRecord.PatientName ?? "未知患者";
                        string safeMedicalCard = paymentRecord.MedicalCard ?? string.Empty;
                        string safePaymentMethod = paymentRecord.PaymentMethod ?? "其他";
                        string safePaymentType = paymentRecord.PaymentType ?? "其他";
                        string safeTransactionNumber = paymentRecord.TransactionNumber ?? string.Empty;
                        string safeOperatorName = paymentRecord.OperatorName ?? "system";
                        string safeRemarks = paymentRecord.Remarks ?? string.Empty;
                        string safeReceiptUrl = paymentRecord.ReceiptUrl ?? string.Empty;
                        string safeCreateUser = paymentRecord.CreateUser ?? "system";
                        
                        // 构建SQL插入语句
                        command.CommandText = @"
                            INSERT INTO paymentrecords (
                                InpatientRegistryId, MedicalCard, PatientName, DepartmentName, 
                                PaymentTime, Amount, PaymentMethod, PaymentType, 
                                TransactionNumber, OperatorName, Remarks, ReceiptUrl, 
                                CreateTime, CreateUser, IsDeleted
                            ) VALUES (
                                @InpatientRegistryId, @MedicalCard, @PatientName, @DepartmentName, 
                                @PaymentTime, @Amount, @PaymentMethod, @PaymentType, 
                                @TransactionNumber, @OperatorName, @Remarks, @ReceiptUrl, 
                                @CreateTime, @CreateUser, @IsDeleted
                            );
                            SELECT LAST_INSERT_ID();";
                        
                        // 添加参数
                        var p1 = command.CreateParameter();
                        p1.ParameterName = "@InpatientRegistryId";
                        p1.Value = paymentRecord.InpatientRegistryId;
                        command.Parameters.Add(p1);
                        
                        var p2 = command.CreateParameter();
                        p2.ParameterName = "@MedicalCard";
                        p2.Value = safeMedicalCard;
                        command.Parameters.Add(p2);
                        
                        var p3 = command.CreateParameter();
                        p3.ParameterName = "@PatientName";
                        p3.Value = safePatientName;
                        command.Parameters.Add(p3);
                        
                        var p4 = command.CreateParameter();
                        p4.ParameterName = "@DepartmentName";
                        p4.Value = safeDepartmentName;
                        command.Parameters.Add(p4);
                        
                        var p5 = command.CreateParameter();
                        p5.ParameterName = "@PaymentTime";
                        p5.Value = paymentRecord.PaymentTime;
                        command.Parameters.Add(p5);
                        
                        var p6 = command.CreateParameter();
                        p6.ParameterName = "@Amount";
                        p6.Value = paymentRecord.Amount;
                        command.Parameters.Add(p6);
                        
                        var p7 = command.CreateParameter();
                        p7.ParameterName = "@PaymentMethod";
                        p7.Value = safePaymentMethod;
                        command.Parameters.Add(p7);
                        
                        var p8 = command.CreateParameter();
                        p8.ParameterName = "@PaymentType";
                        p8.Value = safePaymentType;
                        command.Parameters.Add(p8);
                        
                        var p9 = command.CreateParameter();
                        p9.ParameterName = "@TransactionNumber";
                        p9.Value = safeTransactionNumber;
                        command.Parameters.Add(p9);
                        
                        var p10 = command.CreateParameter();
                        p10.ParameterName = "@OperatorName";
                        p10.Value = safeOperatorName;
                        command.Parameters.Add(p10);
                        
                        var p11 = command.CreateParameter();
                        p11.ParameterName = "@Remarks";
                        p11.Value = safeRemarks;
                        command.Parameters.Add(p11);
                        
                        var p12 = command.CreateParameter();
                        p12.ParameterName = "@ReceiptUrl";
                        p12.Value = safeReceiptUrl;
                        command.Parameters.Add(p12);
                        
                        var p13 = command.CreateParameter();
                        p13.ParameterName = "@CreateTime";
                        p13.Value = paymentRecord.CreateTime;
                        command.Parameters.Add(p13);
                        
                        var p14 = command.CreateParameter();
                        p14.ParameterName = "@CreateUser";
                        p14.Value = safeCreateUser;
                        command.Parameters.Add(p14);
                        
                        var p15 = command.CreateParameter();
                        p15.ParameterName = "@IsDeleted";
                        p15.Value = false;
                        command.Parameters.Add(p15);
                        
                        // 执行SQL并获取新插入记录的ID
                        var newId = Convert.ToInt64(command.ExecuteScalar());
                        paymentRecord.Id = newId;
                        
                        logger.LogInformation($"支付记录保存成功，ID: {newId}");
                    }
                }
                                    catch (Exception ex)
                    {
                        logger.LogError(ex, $"保存支付记录时发生异常: {ex.Message}");
                        if (ex.InnerException != null)
                        {
                            logger.LogError($"内部异常: {ex.InnerException.Message}");
                        }
                        
                        // 获取表结构信息，帮助排查问题
                        try
                        {
                            var connection = db.Database.GetDbConnection();
                            if (connection.State != System.Data.ConnectionState.Open)
                            {
                                connection.Open();
                            }
                            
                            using (var command = connection.CreateCommand())
                            {
                                command.CommandText = "DESCRIBE paymentrecords";
                                using (var reader = command.ExecuteReader())
                                {
                                    logger.LogInformation("表结构信息:");
                                    while (reader.Read())
                                    {
                                        string fieldName = reader.GetString(0);
                                        string fieldType = reader.GetString(1);
                                        string isNullable = reader.GetString(2);
                                        logger.LogInformation($"字段: {fieldName}, 类型: {fieldType}, 可空: {isNullable}");
                                    }
                                }
                            }
                        }
                        catch (Exception tableEx)
                        {
                            logger.LogError(tableEx, "获取表结构信息失败");
                        }
                        
                        throw; // 重新抛出异常，让上层处理
                    }

                                    // 如果是押金缴纳或退款，更新预交款表
                    if (request.PaymentType == "押金缴纳" || request.PaymentType == "退款")
                    {
                        try
                        {
                            // 使用SQL直接查询和更新预交款记录
                            var connection = db.Database.GetDbConnection();
                            if (connection.State != System.Data.ConnectionState.Open)
                            {
                                connection.Open();
                            }
                            
                            // 安全处理字符串值
                            string safeMedicalCard = request.MedicalCard ?? string.Empty;
                            string safePatientName = request.PatientName ?? "未知患者";
                            string safeOperatorName = request.OperatorName ?? "system";
                            
                            // 查询是否存在预交款记录
                            bool prepaymentExists = false;
                            long prepaymentId = 0;
                            decimal currentResiduePrice = 0;
                            
                            using (var command = connection.CreateCommand())
                            {
                                command.CommandText = @"
                                    SELECT Id, ResiduePrice 
                                    FROM prepayments 
                                    WHERE MedicalCard = @MedicalCard AND IsDeleted = 0 
                                    ORDER BY CreateTime DESC 
                                    LIMIT 1";
                                
                                var p1 = command.CreateParameter();
                                p1.ParameterName = "@MedicalCard";
                                p1.Value = safeMedicalCard;
                                command.Parameters.Add(p1);
                                
                                using (var reader = command.ExecuteReader())
                                {
                                    if (reader.Read())
                                    {
                                        prepaymentExists = true;
                                        prepaymentId = reader.GetInt64(0);
                                        currentResiduePrice = reader.GetDecimal(1);
                                    }
                                }
                            }
                            
                            if (prepaymentExists)
                            {
                                // 更新现有预交款记录
                                using (var command = connection.CreateCommand())
                                {
                                    decimal newAmountPrice = currentResiduePrice + request.Amount;
                                    
                                    command.CommandText = @"
                                        UPDATE prepayments 
                                        SET AmountPrice = AmountPrice + @Amount, 
                                            ResiduePrice = ResiduePrice + @Amount 
                                        WHERE Id = @Id";
                                    
                                    var p1 = command.CreateParameter();
                                    p1.ParameterName = "@Amount";
                                    p1.Value = request.Amount;
                                    command.Parameters.Add(p1);
                                    
                                    var p2 = command.CreateParameter();
                                    p2.ParameterName = "@Id";
                                    p2.Value = prepaymentId;
                                    command.Parameters.Add(p2);
                                    
                                    int rowsAffected = command.ExecuteNonQuery();
                                    logger.LogInformation($"已更新预交款记录，ID：{prepaymentId}，新增金额：{request.Amount}，当前剩余金额：{currentResiduePrice + request.Amount}，影响行数：{rowsAffected}");
                                }
                            }
                            else if (request.Amount > 0) // 如果是新的押金缴纳，创建预交款记录
                            {
                                using (var command = connection.CreateCommand())
                                {
                                    command.CommandText = @"
                                        INSERT INTO prepayments (
                                            MedicalCard, PatientName, AmountPrice, ResiduePrice, 
                                            UsedPrice, CreateTime, CreateUser, IsDeleted
                                        ) VALUES (
                                            @MedicalCard, @PatientName, @Amount, @Amount, 
                                            0, @CreateTime, @CreateUser, 0
                                        );
                                        SELECT LAST_INSERT_ID();";
                                    
                                    var p1 = command.CreateParameter();
                                    p1.ParameterName = "@MedicalCard";
                                    p1.Value = safeMedicalCard;
                                    command.Parameters.Add(p1);
                                    
                                    var p2 = command.CreateParameter();
                                    p2.ParameterName = "@PatientName";
                                    p2.Value = safePatientName;
                                    command.Parameters.Add(p2);
                                    
                                    var p3 = command.CreateParameter();
                                    p3.ParameterName = "@Amount";
                                    p3.Value = request.Amount;
                                    command.Parameters.Add(p3);
                                    
                                    var p4 = command.CreateParameter();
                                    p4.ParameterName = "@CreateTime";
                                    p4.Value = DateTime.Now;
                                    command.Parameters.Add(p4);
                                    
                                    var p5 = command.CreateParameter();
                                    p5.ParameterName = "@CreateUser";
                                    p5.Value = safeOperatorName;
                                    command.Parameters.Add(p5);
                                    
                                    var newId = Convert.ToInt64(command.ExecuteScalar());
                                    logger.LogInformation($"已创建新的预交款记录，ID：{newId}，金额：{request.Amount}");
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.LogError(ex, "处理预交款记录时发生异常");
                            // 不抛出异常，继续执行，因为支付记录已经成功创建
                        }
                    }

                logger.LogInformation($"支付记录创建成功，ID：{paymentRecord.Id}");

                result.Data = paymentRecord.Id;
                result.Code = APIEnums.Success;
                result.Msg = "创建支付记录成功";
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "创建支付记录时发生异常");
                result.Code = APIEnums.Error;
                result.Msg = $"创建支付记录失败：{ex.Message}";
            }

            return Task.FromResult(result);
        }
    }
} 